import { HvigorNode, HvigorPlugin, Json5Reader } from '@ohos/hvigor';
import { log, ModularityConfig, ModuleConfig } from './ModularityGeneratePlugin';
import * as fs from 'fs'
import path from 'path';
import Handlebars from "handlebars";
import { RouterGenerate } from './RouterGenerate';

const IGNOREPATHS = [
    ".hvigor",
    ".idea",
    ".git",
    "AppScope",
    "oh_modules",
    "common_router",
    "hvigor"
]

export class ModuleConfigurator {

    static configModule(node: HvigorNode, config?: ModularityConfig) {
        const projectPath = node.getNodePath()
        let moduleDirList: string[] = []
        moduleDirList.push(...this.getModuleByFilter(projectPath, projectPath, config?.scanModules))


        let routerMapList: string[] = []
        let componentFileList: RouterConstant[] = []
        moduleDirList.forEach(item => {
            const module = item.substring(item.lastIndexOf("/") + 1, item.length)
            const moduleConfig = config?.scanModules?.find(v => v.name == module)
            RouterGenerate.buildRouter(projectPath, item, (routerMapPath, componentFielPath) => {
                routerMapList.push(routerMapPath)
                componentFileList.push(...componentFielPath)
            }, moduleConfig?.scanPackages, moduleConfig?.ignorePackages)
        })

        // const cachePath = projectPath + "/.hvigor/cache"
        // if (!fs.existsSync(cachePath)) {
        //     fs.mkdirSync(cachePath, { recursive: true });
        // }
        let filterModuleDirList = moduleDirList
        // try {
        //     let cacheModulesJson = fs.readFileSync(cachePath + "/modules.json", { encoding: "utf8" })
        //     let cacheModulesList = JSON.parse(cacheModulesJson) as Array<string>
        //     let hasCache = cacheModulesList.every(item => moduleDirList.includes(item))
        //     if (hasCache) {
        //         log("存在缓存")
        //         return
        //     }
        //     filterModuleDirList = moduleDirList.filter(value => !cacheModulesJson.includes(value))
        // } catch {

        // }

        // fs.writeFileSync(cachePath + "/modules.json", JSON.stringify(moduleDirList, null, 2), { encoding: "utf8" })
        // log("moduleDireList写入缓存-" + JSON.stringify(moduleDirList))
        log("待配置模块-" + JSON.stringify(filterModuleDirList))
        this.configPackageJson(projectPath, filterModuleDirList)

        log("路由集合写入 common_router" + JSON.stringify(routerMapList))
        this.appendRouterMap(projectPath, routerMapList)

        log("待替换 路由为枚举常量的页面-" + JSON.stringify(componentFileList, null, 2))
        componentFileList.forEach(item => {
            let nameSub = item.name!.substring(1, item.name!.length)
            let componentString = fs.readFileSync(item.path!, { encoding: "utf8" })
            const imports = this.extractImports(item.path!)
            const commonRouterImport = imports.find(item => {
                return item.modulePath == "@satis/common-router"
            })
            let content = componentString
            if (commonRouterImport) {
                if (!commonRouterImport.importedItems.includes("RouterEnum")) {
                    let newImport = "import { "
                    commonRouterImport.importedItems.forEach(importedItem => {
                        if (newImport == "import { ") {
                            newImport = newImport + importedItem
                        } else {
                            newImport = newImport + "," + importedItem
                        }
                    })
                    newImport = newImport + ",RouterEnum"
                    newImport = newImport + " } from" + `'${commonRouterImport.modulePath}'`
                    log("页面" + item.path + "-将" + commonRouterImport.importSource + "修改为" + newImport)
                    content = componentString.replace(commonRouterImport.importSource, newImport)
                } else {
                    log("已存在 RouterEnum 导入，无需添加")
                }
            } else {
                content = "import {RouterEnum} from  '@satis/common-router'\n" + content
                log("页面" + item.path + "-添加 import {RouterEnum} from  '@satis/common-router' 导入")
            }
            let enumConst = "RouterEnum." + nameSub.split("/").join("_").toUpperCase()
            content = content.replace(`"${item.name}"`, enumConst).replace(`'${item.name}'`, enumConst)
            log("替换 " + item.path + "页面中声明的router name-" + item.name + " 为枚举" + enumConst)
            fs.writeFileSync(item.path!, content)
        })

    }

    static extractImports(filePath: string) {
        const fileContent = fs.readFileSync(filePath, 'utf-8');
        const importRegex = /import\s*{([^}]+)}\s*from\s*['"]([^'"]+)['"]/g;
        const imports = [];

        let match;
        while ((match = importRegex.exec(fileContent)) !== null) {
            const importSource = match[0]
            const importedItems = match[1].split(',').map(item => item.trim());
            const modulePath = match[2];
            imports.push({ importSource, modulePath, importedItems });
        }

        return imports;
    }


    static configPackageJson(projectPath: string, filterModuleDirList: string[]) {
        filterModuleDirList.forEach(item => {
            const packageJson5 = Json5Reader.getJson5Obj(item + "/oh-package.json5", "utf8")
            const packageJson5Obj = JSON.parse(JSON.stringify(packageJson5))
            const dependencies = packageJson5Obj.dependencies
            let modularityDep: any | undefined
            let ohRouterDep: any | undefined
            if (dependencies) {
                modularityDep = dependencies["@satis/common-router"]
                ohRouterDep = dependencies["@satis/oh-router"]
            } else {
                packageJson5Obj.dependencies = {}
            }
            if (!modularityDep) {
                // 未配置 则配置
                log("配置模块" + item + "的 common_router 依赖")
                let commonRouterDep = "file:"
                item.replace(projectPath + "/", "").split("/").forEach(() => {
                    commonRouterDep += "../"
                })
                commonRouterDep += "common_router"
                packageJson5Obj.dependencies["@satis/common-router"] = commonRouterDep
            }

            if (!ohRouterDep) {
                packageJson5Obj.dependencies["@satis/oh-router"] = "^1.0.5"
            }

            if (!modularityDep || !ohRouterDep) {
                fs.writeFileSync(item + "/oh-package.json5", JSON.stringify(packageJson5Obj, null, 2))
            }
        })
    }

    static getModuleByFilter(modulePath: string, filePath: string, scanModules: ModuleConfig[] | undefined): string[] {
        if (scanModules && scanModules.length > 0) {
            return scanModules.map(value => filePath + '/' + value.name)
        }
        if (!filePath) {
            return []
        }

        // 过滤系统目录
        if (IGNOREPATHS.includes(filePath.replace(modulePath + "/", ""))) {
            return []
        }
        const stats = fs.lstatSync(filePath)
        const moduleDirList: string[] = []
        if (stats.isDirectory()) {
            let hasPackageJson5 = false
            try {
                hasPackageJson5 = fs.statSync(filePath + "/oh-package.json5").isFile()
            } catch {
            }
            if (filePath != modulePath && hasPackageJson5) {
                moduleDirList.push(filePath)
                return moduleDirList
            }
            fs.readdirSync(filePath).forEach(file => {
                const fullPath = path.join(filePath, file);
                if (fs.statSync(fullPath).isDirectory()) {
                    moduleDirList.push(...this.getModuleByFilter(modulePath, fullPath, undefined))
                }
            });
            return moduleDirList
        } else {
            return []
        }
    }

    static appendRouterMap(projectPath: string, routerMapList: string[]) {
        let allRouterMapList: any[] = []
        routerMapList.forEach(routerMapPath => {
            let routerMapObj = JSON.parse(fs.readFileSync(routerMapPath, { encoding: "utf8" }))
            allRouterMapList.push(...routerMapObj.routerMap)
        })

        this.definedRouterConstant(projectPath, allRouterMapList)
    }

    static definedRouterConstant(projectPath: string, allRouterConstantList: any[]) {
        let list = allRouterConstantList.map(item => {
            const s = item.name.substring(1, item.name.length) as string
            const s1 = s.split("/").join("_")
            return {
                name: s1.toUpperCase(),
                item: item
            }
        })

        const enumValue = this.readEnumValue(projectPath)
        log("已有枚举的路由-" + JSON.stringify(enumValue, null, 2))

        list = list.filter((item) => {
            if (enumValue[item.name]) {
                return false
            } else {
                return true
            }
        })

        log("需要添加枚举的路由-" + JSON.stringify(list, null, 2))

        if (list.length > 0) {
            const routerEnumPath = __dirname + "/router-constant.tpl";
            const routerEnumTpl = fs.readFileSync(routerEnumPath, { encoding: "utf8" });
            const routerEnum = fs.readFileSync(projectPath + "/common_router/src/main/ets/RouterEnum.ets", { encoding: "utf8" })

            const routerEnumTemplate = Handlebars.compile(routerEnum.replace("/**generate-flow**/", routerEnumTpl));
            const output = routerEnumTemplate({
                routerMapList: list,
            });
            log("写入所有路由的 枚举声明- /common_router/src/main/ets/RouterEnum.ets")
            fs.writeFileSync(projectPath + "/common_router/src/main/ets/RouterEnum.ets", output, { encoding: "utf8" });
        }


        const intercepterList = allRouterConstantList.filter(item => item.data?.interceptionTag)
        const interceptMapPath = __dirname + "/router-intercept.tpl";
        const interceptMapTpl = fs.readFileSync(interceptMapPath, { encoding: "utf8" });


        const interceptMapTemplate = Handlebars.compile(interceptMapTpl);
        log("需拦截路由-" + JSON.stringify(intercepterList, null, 2))
        const interceptOutput = interceptMapTemplate({
            intercepterList: intercepterList
        });
        log("写入需要拦截配置的路由集合- /common_router/src/main/ets/InterceptMap.ets")
        fs.writeFileSync(projectPath + "/common_router/src/main/ets/InterceptMap.ets", interceptOutput, { encoding: "utf8" });
    }

    static readEnumValue(projectPath: string): { [key: string]: string } {
        const enumPath = projectPath + "/common_router/src/main/ets/RouterEnum.ets"
        const enumFileContent = fs.readFileSync(enumPath, 'utf-8');
        const enumKeyValues: { [key: string]: string } = {};
        const enumRegex = /export\s+enum\s+\w+\s*{([^}]*)}/gm;
        const keyValueRegex = /(\w+)\s*=\s*["']([^"']+)["']/g;

        let enumMatch;
        while ((enumMatch = enumRegex.exec(enumFileContent)) !== null) {
            let keyValueMatch;
            while ((keyValueMatch = keyValueRegex.exec(enumMatch[1])) !== null) {
                enumKeyValues[keyValueMatch[1]] = keyValueMatch[2];
            }
        }
        log("扫描枚举值-" + JSON.stringify(enumKeyValues))
        return enumKeyValues
    }
}


export class RouterConstant {
    name: string | undefined
    path: string | undefined
}

